package database

import (
	"fmt"
	"time"

	"changeme/internal/models"
)

// ErrorCode 错误代码类型
type ErrorCode string

const (
	// 连接错误
	ErrCodeConnectionFailed     ErrorCode = "CONNECTION_FAILED"
	ErrCodeConnectionTimeout    ErrorCode = "CONNECTION_TIMEOUT"
	ErrCodeConnectionClosed     ErrorCode = "CONNECTION_CLOSED"
	ErrCodeAuthenticationFailed ErrorCode = "AUTH_FAILED"

	// 查询错误
	ErrCodeSyntaxError         ErrorCode = "SYNTAX_ERROR"
	ErrCodeTableNotFound       ErrorCode = "TABLE_NOT_FOUND"
	ErrCodeColumnNotFound      ErrorCode = "COLUMN_NOT_FOUND"
	ErrCodeDuplicateKey        ErrorCode = "DUPLICATE_KEY"
	ErrCodeForeignKeyViolation ErrorCode = "FK_VIOLATION"
	ErrCodeDataTypeMismatch    ErrorCode = "TYPE_MISMATCH"

	// 事务错误
	ErrCodeDeadlock           ErrorCode = "DEADLOCK"
	ErrCodeTransactionAborted ErrorCode = "TX_ABORTED"

	// 权限错误
	ErrCodeAccessDenied           ErrorCode = "ACCESS_DENIED"
	ErrCodeInsufficientPrivileges ErrorCode = "INSUFFICIENT_PRIVILEGES"

	// 资源错误
	ErrCodeOutOfMemory  ErrorCode = "OUT_OF_MEMORY"
	ErrCodeDiskFull     ErrorCode = "DISK_FULL"
	ErrCodeQueryTimeout ErrorCode = "QUERY_TIMEOUT"

	// 通用错误
	ErrCodeUnknown ErrorCode = "UNKNOWN_ERROR"
)

// DatabaseError 数据库错误
type DatabaseError struct {
	Code       ErrorCode
	Message    string
	DBType     models.DatabaseType
	Query      string
	Underlying error
	Timestamp  time.Time
	Context    map[string]interface{}
}

// Error 实现error接口
func (e *DatabaseError) Error() string {
	if e.Query != "" {
		return fmt.Sprintf("[%s] %s: %s (Query: %.100s...)", e.DBType, e.Code, e.Message, e.Query)
	}
	return fmt.Sprintf("[%s] %s: %s", e.DBType, e.Code, e.Message)
}

// Unwrap 返回底层错误
func (e *DatabaseError) Unwrap() error {
	return e.Underlying
}

// IsRetryable 判断错误是否可重试
func (e *DatabaseError) IsRetryable() bool {
	switch e.Code {
	case ErrCodeConnectionTimeout, ErrCodeDeadlock, ErrCodeQueryTimeout:
		return true
	default:
		return false
	}
}

// IsConstraintViolation 检查是否为约束违反错误
func (e *DatabaseError) IsConstraintViolation() bool {
	switch e.Code {
	case ErrCodeDuplicateKey, ErrCodeForeignKeyViolation:
		return true
	default:
		return false
	}
}

// GetSQLState 获取SQL状态码（如果可用）
func (e *DatabaseError) GetSQLState() string {
	// 从上下文中获取 SQL STATE，如果存在的话
	if state, ok := e.Context["sqlstate"]; ok {
		if stateStr, ok := state.(string); ok {
			return stateStr
		}
	}
	return ""
}

// NewDatabaseError 创建数据库错误
func NewDatabaseError(code ErrorCode, message string, dbType models.DatabaseType, underlying error) *DatabaseError {
	return &DatabaseError{
		Code:       code,
		Message:    message,
		DBType:     dbType,
		Underlying: underlying,
		Timestamp:  time.Now(),
		Context:    make(map[string]interface{}),
	}
}

// WithQuery 添加查询信息
func (e *DatabaseError) WithQuery(query string) *DatabaseError {
	e.Query = query
	return e
}

// WithContext 添加上下文信息
func (e *DatabaseError) WithContext(key string, value interface{}) *DatabaseError {
	if e.Context == nil {
		e.Context = make(map[string]interface{})
	}
	e.Context[key] = value
	return e
}

// ErrorParser 错误解析器接口
type ErrorParser interface {
	ParseError(err error, dbType models.DatabaseType) *DatabaseError
}

// BaseErrorParser 基础错误解析器
type BaseErrorParser struct{}

// ParseError 解析错误
func (p *BaseErrorParser) ParseError(err error, dbType models.DatabaseType) *DatabaseError {
	if err == nil {
		return nil
	}

	// 如果已经是DatabaseError，直接返回
	if dbErr, ok := err.(*DatabaseError); ok {
		return dbErr
	}

	// 通用错误处理
	return NewDatabaseError(ErrCodeUnknown, err.Error(), dbType, err)
}

// MySQLErrorParser MySQL错误解析器
type MySQLErrorParser struct {
	BaseErrorParser
}

// ParseError 解析MySQL错误
func (p *MySQLErrorParser) ParseError(err error, dbType models.DatabaseType) *DatabaseError {
	if err == nil {
		return nil
	}

	errMsg := err.Error()

	// MySQL特定错误代码映射
	errorMappings := map[string]ErrorCode{
		"Error 1045": ErrCodeAuthenticationFailed,
		"Error 1146": ErrCodeTableNotFound,
		"Error 1054": ErrCodeColumnNotFound,
		"Error 1062": ErrCodeDuplicateKey,
		"Error 1452": ErrCodeForeignKeyViolation,
		"Error 1213": ErrCodeDeadlock,
		"Error 1044": ErrCodeAccessDenied,
		"Error 1064": ErrCodeSyntaxError,
	}

	for pattern, code := range errorMappings {
		if contains(errMsg, pattern) {
			return NewDatabaseError(code, errMsg, models.MySQL, err)
		}
	}

	return p.BaseErrorParser.ParseError(err, models.MySQL)
}

// PostgreSQLErrorParser PostgreSQL错误解析器
type PostgreSQLErrorParser struct {
	BaseErrorParser
}

// ParseError 解析PostgreSQL错误
func (p *PostgreSQLErrorParser) ParseError(err error, dbType models.DatabaseType) *DatabaseError {
	if err == nil {
		return nil
	}

	errMsg := err.Error()

	// PostgreSQL错误代码映射
	errorMappings := map[string]ErrorCode{
		"28P01": ErrCodeAuthenticationFailed,
		"42P01": ErrCodeTableNotFound,
		"42703": ErrCodeColumnNotFound,
		"23505": ErrCodeDuplicateKey,
		"23503": ErrCodeForeignKeyViolation,
		"40P01": ErrCodeDeadlock,
		"42501": ErrCodeInsufficientPrivileges,
		"42601": ErrCodeSyntaxError,
		"57014": ErrCodeQueryTimeout,
	}

	for code, errCode := range errorMappings {
		if contains(errMsg, code) {
			return NewDatabaseError(errCode, errMsg, models.PostgreSQL, err)
		}
	}

	return p.BaseErrorParser.ParseError(err, models.PostgreSQL)
}

// SQLServerErrorParser SQL Server错误解析器
type SQLServerErrorParser struct {
	BaseErrorParser
}

// ParseError 解析SQL Server错误
func (p *SQLServerErrorParser) ParseError(err error, dbType models.DatabaseType) *DatabaseError {
	if err == nil {
		return nil
	}

	errMsg := err.Error()

	// SQL Server错误代码映射
	errorMappings := map[string]ErrorCode{
		"18456": ErrCodeAuthenticationFailed,
		"208":   ErrCodeTableNotFound,
		"207":   ErrCodeColumnNotFound,
		"2627":  ErrCodeDuplicateKey,
		"547":   ErrCodeForeignKeyViolation,
		"1205":  ErrCodeDeadlock,
		"229":   ErrCodeAccessDenied,
		"156":   ErrCodeSyntaxError,
	}

	for code, errCode := range errorMappings {
		if contains(errMsg, "Error "+code) {
			return NewDatabaseError(errCode, errMsg, models.SQLServer, err)
		}
	}

	return p.BaseErrorParser.ParseError(err, models.SQLServer)
}

// DaMengErrorParser 达梦错误解析器
type DaMengErrorParser struct {
	BaseErrorParser
}

// ParseError 解析达梦错误
func (p *DaMengErrorParser) ParseError(err error, dbType models.DatabaseType) *DatabaseError {
	if err == nil {
		return nil
	}

	errMsg := err.Error()

	// 达梦错误代码映射
	errorMappings := map[string]ErrorCode{
		"Error -2007": ErrCodeSyntaxError,
		"Error -2106": ErrCodeTableNotFound,
		"Error -2117": ErrCodeColumnNotFound,
		"Error -2116": ErrCodeDuplicateKey,
		"Error -2291": ErrCodeForeignKeyViolation,
		"Error -70":   ErrCodeDeadlock,
		"Error -531":  ErrCodeAccessDenied,
	}

	for pattern, code := range errorMappings {
		if contains(errMsg, pattern) {
			return NewDatabaseError(code, errMsg, models.DaMeng, err)
		}
	}

	return p.BaseErrorParser.ParseError(err, models.DaMeng)
}

// GetErrorParser 根据数据库类型获取错误解析器
func GetErrorParser(dbType models.DatabaseType) ErrorParser {
	switch dbType {
	case models.MySQL:
		return &MySQLErrorParser{}
	case models.PostgreSQL:
		return &PostgreSQLErrorParser{}
	case models.SQLServer:
		return &SQLServerErrorParser{}
	case models.DaMeng:
		return &DaMengErrorParser{}
	default:
		return &BaseErrorParser{}
	}
}

// contains 判断字符串是否包含子串
func contains(str, substr string) bool {
	return len(str) >= len(substr) && (str == substr || len(substr) == 0 ||
		(len(str) > len(substr) && containsHelper(str, substr)))
}

func containsHelper(str, substr string) bool {
	for i := 0; i <= len(str)-len(substr); i++ {
		if str[i:i+len(substr)] == substr {
			return true
		}
	}
	return false
}
